﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using Linker.LinkerException;

namespace Communication.Transporter.Linker
{
    public class SimpleSocket
    {
        private Socket _Socket;
        private IPAddress _LocalIPAddress;
        public static int MAX_MESSAGE_LENGTH = 16384;

        public Socket Socket
        {
            get { return _Socket; }
            set { _Socket = value; }
        }

        public IPAddress LocalIPAddress
        {
            get 
            {
                if (this._LocalIPAddress == null)
                {
                    IPAddress[] localIPArr = Dns.GetHostAddresses(Dns.GetHostName());
                    foreach (var item in localIPArr)
                    {
                        if (AddressFamily.InterNetwork == item.AddressFamily)
                        {
                            this._LocalIPAddress = item;
                        }
                    }
                }
                return this._LocalIPAddress; 
            }
        }

        public SimpleSocket(int numberOfClient)
        {
            this._Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        private SimpleSocket(Socket clientSocket)
        {
            this._Socket = clientSocket;
        }

        public void InitLocal(int port)
        {
            IPEndPoint iep = new IPEndPoint(this._LocalIPAddress, port);
            this._Socket.Bind(iep);
        }

        public void Listen(int numberOfClient)
        {
            this._Socket.Listen(numberOfClient);
        }

        public void Connect(string serverIP, int serverListeningPort)
        {
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse(serverIP), serverListeningPort);
            this._Socket.Connect(iep);
        }

        public SimpleSocket Accept()
        {
            return new SimpleSocket(this._Socket.Accept());
        }

        public void SendUnicodeMessage(String message)
        {
            byte[] data = Encoding.Unicode.GetBytes(message);
            if (data.Length <= MAX_MESSAGE_LENGTH)
            {
                this._Socket.Send(data, SocketFlags.None);
            }
            else
            {
                throw LinkerSocketException.GetInstance(LinkerSocketException.MESSAGE_OUT_OF_LENGTH);
            }
        }

        public string ReceiveString()
        {
            byte[] data = new byte[MAX_MESSAGE_LENGTH];
            this._Socket.Receive(data);
            return Encoding.Unicode.GetString(data);
        }

        public void Close()
        {
            this._Socket.Close();
        }

        public void ShutDown(SocketShutdown how)
        {
            this._Socket.Shutdown(how);
        }
    }
}
